package com.godenwater.recv.decode;

import org.apache.mina.core.buffer.IoBuffer;

import cn.gov.mwr.sl651.AbstractParser;
import cn.gov.mwr.sl651.Symbol;
import cn.gov.mwr.sl651.utils.ByteUtil;

import com.godenwater.recv.model.CommonMessage;

/**
 * 水文协议报文解析器
 * 
 * @author admin
 *
 */
public class Sl651MessageDecoder {

	public static CommonMessage decodeAsc(IoBuffer buffer) {

		cn.gov.mwr.sl651.header.AscHeader header = new cn.gov.mwr.sl651.header.AscHeader();
		header.setStartBit(new byte[] { Symbol.SOH_ASC });

		// 上行的，中心站地址在前
		byte[] centerAddr = new byte[header.getCenterAddrLen()];
		buffer.get(centerAddr);
		header.setCenterAddr(centerAddr);

		// 上行的，遥测站地址在前
		byte[] stationAddr = new byte[header.getStationAddrLen()];
		buffer.get(stationAddr);
		header.setStationAddr(stationAddr);

		byte[] password = new byte[header.getPasswordLen()];
		buffer.get(password);
		header.setPassword(password);

		byte[] funcCode = new byte[header.getFuncCodeLen()];
		buffer.get(funcCode);
		header.setFuncCode(funcCode);

		byte[] BodySize = new byte[header.getBodySizeLen()];
		buffer.get(BodySize);
		String hexBodySizeStr = new String(BodySize);
		byte[] hexBodySize = ByteUtil.HexStringToBinary(hexBodySizeStr);
		header.setBodySize(BodySize);

		byte[] bodyStartBit = new byte[header.getBodyStartBitLen()];
		buffer.get(bodyStartBit);
		header.setBodyStartBit(bodyStartBit);

		if (header.getBodyStartBit()[0] == Symbol.SYN) {
			byte[] bodyCount = new byte[header.getBodyCountLen()];
			buffer.get(bodyCount);
			header.setBodyCount(bodyCount);
		}

		// 转换报文中的上下行标识及报文长度
		int bodySizeLen = AbstractParser.parseLength(hexBodySize);// 需要考虑拆分字节;
		if (bodyStartBit[0] == Symbol.SYN) {
			bodySizeLen = bodySizeLen - header.getBodyCountLen();
		}
		int crclen = 4;

		// --------------------------------
		CommonMessage message = new CommonMessage();
		message.setHeader(header);
		message.setCrclen(crclen);
		message.setBodySize(bodySizeLen);

		return message;
	}

	public static CommonMessage decodeAsc(byte[] buffer) {

		cn.gov.mwr.sl651.header.AscHeader header = new cn.gov.mwr.sl651.header.AscHeader();

		int pos = 0;

		byte[] startBit = new byte[header.getStartBitLen()];
		System.arraycopy(buffer, pos, startBit, 0, startBit.length);
		pos = pos + header.getStartBitLen();
		header.setStartBit(startBit);

		// 上行的，中心站地址在前
		byte[] centerAddr = new byte[header.getCenterAddrLen()];
		System.arraycopy(buffer, pos, centerAddr, 0, centerAddr.length);
		pos = pos + header.getCenterAddrLen();
		header.setCenterAddr(centerAddr);

		// 上行的，遥测站地址在前
		byte[] stationAddr = new byte[header.getStationAddrLen()];
		System.arraycopy(buffer, pos, stationAddr, 0, stationAddr.length);
		pos = pos + header.getStationAddrLen();
		header.setStationAddr(stationAddr);

		// 解析密码
		byte[] password = new byte[header.getPasswordLen()];
		System.arraycopy(buffer, pos, password, 0, password.length);
		pos = pos + header.getPasswordLen();
		header.setPassword(password);

		// 解析 功能码
		byte[] funcCode = new byte[header.getFuncCodeLen()];
		System.arraycopy(buffer, pos, funcCode, 0, funcCode.length);
		pos = pos + header.getFuncCodeLen();
		header.setFuncCode(funcCode);

		byte[] BodySize = new byte[header.getBodySizeLen()];
		System.arraycopy(buffer, pos, BodySize, 0, BodySize.length);
		pos = pos + header.getBodySizeLen();

		String hexBodySizeStr = new String(BodySize);
		byte[] hexBodySize = ByteUtil.HexStringToBinary(hexBodySizeStr);
		header.setBodySize(BodySize);

		byte[] bodyStartBit = new byte[header.getBodyStartBitLen()];
		System.arraycopy(buffer, pos, bodyStartBit, 0, bodyStartBit.length);
		pos = pos + header.getBodyStartBitLen();
		header.setBodyStartBit(bodyStartBit);

		// 如果是SYN，表示是多包发送。多包发送，一次确认的传输模式中使用

		if (header.getBodyStartBit()[0] == Symbol.SYN) {
			byte[] bodyCount = new byte[header.getBodyCountLen()];
			System.arraycopy(buffer, pos, bodyCount, 0, bodyCount.length);
			pos = pos + header.getBodyCountLen();
			header.setBodyCount(bodyCount);
		}

		// 转换报文中的上下行标识及报文长度
		int bodySizeLen = AbstractParser.parseLength(hexBodySize);// 需要考虑拆分字节;
		if (bodyStartBit[0] == Symbol.SYN) {
			bodySizeLen = bodySizeLen - header.getBodyCountLen();
		}
		int crclen = 4;

		// --------------------------------
		CommonMessage message = new CommonMessage();
		message.setHeader(header);
		message.setCrclen(crclen);
		message.setBodySize(bodySizeLen);

		return message;
	}

	public static CommonMessage decodeHex(IoBuffer buffer) {

		cn.gov.mwr.sl651.header.HexHeader header = new cn.gov.mwr.sl651.header.HexHeader();

		header.setStartBit(new byte[] { Symbol.SOH_HEX, Symbol.SOH_HEX });

		// 上行的，中心站地址在前
		byte[] centerAddr = new byte[header.getCenterAddrLen()];
		buffer.get(centerAddr);
		header.setCenterAddr(centerAddr);

		// 上行的，遥测站地址在后
		byte[] stationAddr = new byte[header.getStationAddrLen()];
		buffer.get(stationAddr);
		header.setStationAddr(stationAddr);

		// 解析密码
		byte[] password = new byte[header.getPasswordLen()];
		buffer.get(password);
		header.setPassword(password);

		// 解析 功能码
		byte[] funcCode = new byte[header.getFuncCodeLen()];
		buffer.get(funcCode);
		header.setFuncCode(funcCode);

		// 解析报文上行标识及消息体长度
		byte[] BodySize = new byte[header.getBodySizeLen()];
		buffer.get(BodySize);
		header.setBodySize(BodySize);

		// 解析消息开始体
		byte[] bodyStartBit = new byte[header.getBodyStartBitLen()];
		buffer.get(bodyStartBit);
		header.setBodyStartBit(bodyStartBit);

		// 如果是SYN，表示是多包发送。多包发送，一次确认的传输模式中使用
		if (bodyStartBit[0] == Symbol.SYN) {
			byte[] bodyCount = new byte[header.getBodyCountLen()];
			buffer.get(bodyCount);
			header.setBodyCount(bodyCount);
		}

		// 转换报文中的上下行标识及报文长度
		int bodySizeLen = AbstractParser.parseLength(BodySize);// 需要考虑拆分字节;
		 if (bodyStartBit[0] == Symbol.SYN) { //燕禹的协议未将此字节算做报文的字节
		 	bodySizeLen = bodySizeLen - header.getBodyCountLen();
		 }
		int crclen = 2;

		// --------------------------------
		CommonMessage message = new CommonMessage();
		message.setHeader(header);
		message.setCrclen(crclen);
		message.setBodySize(bodySizeLen);

		return message;
	}

	/**
	 * 根据字节解析
	 * 
	 * @param buffer
	 * @return
	 */
	public static CommonMessage decodeHex(byte[] buffer) {

		cn.gov.mwr.sl651.header.HexHeader header = new cn.gov.mwr.sl651.header.HexHeader();

		header.setStartBit(new byte[] { Symbol.SOH_HEX, Symbol.SOH_HEX });

		int pos = 2;
		// 上行的，中心站地址在前
		byte[] centerAddr = new byte[header.getCenterAddrLen()];
		System.arraycopy(buffer, pos, centerAddr, 0, centerAddr.length);
		pos = pos + header.getCenterAddrLen();
		header.setCenterAddr(centerAddr);

		// 上行的，遥测站地址在后
		byte[] stationAddr = new byte[header.getStationAddrLen()];
		System.arraycopy(buffer, pos, stationAddr, 0, stationAddr.length);
		pos = pos + header.getStationAddrLen();
		header.setStationAddr(stationAddr);

		// 解析密码
		byte[] password = new byte[header.getPasswordLen()];
		System.arraycopy(buffer, pos, password, 0, password.length);
		pos = pos + header.getPasswordLen();
		header.setPassword(password);

		// 解析 功能码
		byte[] funcCode = new byte[header.getFuncCodeLen()];
		System.arraycopy(buffer, pos, funcCode, 0, funcCode.length);
		pos = pos + header.getFuncCodeLen();
		header.setFuncCode(funcCode);

		// 解析报文上行标识及消息体长度
		byte[] BodySize = new byte[header.getBodySizeLen()];
		System.arraycopy(buffer, pos, BodySize, 0, BodySize.length);
		pos = pos + header.getBodySizeLen();
		header.setBodySize(BodySize);

		// 解析消息开始体
		byte[] bodyStartBit = new byte[header.getBodyStartBitLen()];
		System.arraycopy(buffer, pos, bodyStartBit, 0, bodyStartBit.length);
		pos = pos + header.getBodyStartBitLen();
		header.setBodyStartBit(bodyStartBit);

		// 如果是SYN，表示是多包发送。多包发送，一次确认的传输模式中使用
		if (bodyStartBit[0] == Symbol.SYN) {
			byte[] bodyCount = new byte[header.getBodyCountLen()];
			System.arraycopy(buffer, pos, bodyCount, 0, bodyCount.length);
			pos = pos + header.getBodyCountLen();
			header.setBodyCount(bodyCount);
		}

		// 转换报文中的上下行标识及报文长度
		int bodySizeLen = AbstractParser.parseLength(BodySize);// 需要考虑拆分字节;
		if (bodyStartBit[0] == Symbol.SYN) {
			bodySizeLen = bodySizeLen - header.getBodyCountLen();
		}

		byte[] bodyContent = new byte[bodySizeLen];// 根据前面header的内容来获取长度
		System.arraycopy(buffer, pos, bodyContent, 0, bodyContent.length);
		pos = pos + bodySizeLen;

		// 终止符
		byte[] eof = new byte[1];
		System.arraycopy(buffer, pos, eof, 0, eof.length);
		pos = pos + eof.length;
		// 校验码
		int crclen = 2;
		byte[] crc = new byte[crclen];
		System.arraycopy(buffer, pos, crc, 0, crc.length);
		pos = pos + crc.length;

		// 组装消息
		// message.setHeader(message.getHeader());
		// --------------------------------
		CommonMessage message = new CommonMessage();
		message.setHeader(header);
		message.setCrclen(crclen);
		message.setBodySize(bodySizeLen);
		message.setContents(bodyContent);
		message.setEOF(eof[0]);
		message.setCRC(crc);

		return message;
	}

}
